package com.kantboot.user.account.service.impl;

import com.kantboot.functional.verification.code.domain.dto.SendVerificationCodeDTO;
import com.kantboot.functional.verification.code.domain.enums.VerificationCodeTypeCodeEnum;
import com.kantboot.functional.verification.code.service.IFunctionalVerificationCodeService;
import com.kantboot.user.account.domain.dto.UserAccountSendVerificationCodeDTO;
import com.kantboot.user.account.domain.entity.UserAccount;
import com.kantboot.user.account.domain.enums.UserAccountVerificationCodeSceneCodeEnums;
import com.kantboot.user.account.domain.vo.LoginVO;
import com.kantboot.user.account.repostiroy.UserAccountRepository;
import com.kantboot.user.account.service.IUserAccountLoginService;
import com.kantboot.user.account.service.IUserAccountService;
import com.kantboot.user.account.service.IUserAccountTokenService;
import com.kantboot.util.common.exception.BaseException;
import com.kantboot.util.common.password.KantbootPassword;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserAccountLoginServiceImpl implements IUserAccountLoginService {

    @Resource
    private UserAccountRepository repository;

    @Resource
    private IUserAccountService userAccountService;

    @Resource
    private IUserAccountTokenService userAccountTokenService;

    @Resource
    private IFunctionalVerificationCodeService verificationCodeService;

    @Resource
    private KantbootPassword kantbootPassword;


    @Override
    public LoginVO loginByUsernameAndPassword(String username, String password) {
        UserAccount byUsername = repository.findByUsername(username);
        if (byUsername == null) {
            // 账号或密码错误
            throw BaseException.of("usernameOrPasswordError", "账号或密码错误");
        }
        // 如果密码为空
        if (byUsername.getPassword() == null) {
            // 该账号未设置密码
            throw BaseException.of("passwordNotSet", "该账号未设置密码");
        }
        // 密码校验
        if (!kantbootPassword.matches(password, byUsername.getPassword())) {
            // 账号或密码错误
            throw BaseException.of("usernameOrPasswordError", "账号或密码错误");
        }

        // 生成令牌
        String token = userAccountTokenService.generateToken(byUsername.getId());
        return new LoginVO()
                .setToken(token)
                .setUserAccount(byUsername);
    }

    /**
     * 发送登录验证码
     *
     * @param userAccountSendVerificationCodeDTO 发送验证码的DTO
     */
    @Override
    public void sendLoginVerificationCode(UserAccountSendVerificationCodeDTO userAccountSendVerificationCodeDTO) {
        // 接受者
        String to = userAccountSendVerificationCodeDTO.getTo();
        // 手机区号，如果是邮箱则不需要
        String phoneAreaCode = userAccountSendVerificationCodeDTO.getPhoneAreaCode();
        // 类型编码
        String typeCode = userAccountSendVerificationCodeDTO.getTypeCode();

        SendVerificationCodeDTO sendVerificationCodeDTO = new SendVerificationCodeDTO()
                .setPhoneAreaCode(phoneAreaCode)
                .setTo(to)
                .setTypeCode(typeCode)
                .setSceneCode(UserAccountVerificationCodeSceneCodeEnums.LOGIN);
        verificationCodeService.send(sendVerificationCodeDTO);
    }

    @Override
    public LoginVO loginByPhoneAndVerificationCode(String phoneAreaCode, String phone, String verificationCode) {
        SendVerificationCodeDTO sendVerificationCodeDTO = new SendVerificationCodeDTO()
                .setPhoneAreaCode(phoneAreaCode)
                .setTo(phone)
                .setTypeCode(VerificationCodeTypeCodeEnum.SMS)
                .setSceneCode(UserAccountVerificationCodeSceneCodeEnums.LOGIN);
        // 验证码白名单
        List<String> phoneOfWhiteList = List.of("13155908637", "17679088643", "13155908601", "13155908602","19966534017");
        for (String s : phoneOfWhiteList) {
            if (s.equals(phone)) {
                phoneAreaCode = "86";
                // 根据手机号查询用户
                UserAccount byPhone = repository.findByPhoneAreaCodeAndPhone(phoneAreaCode, phone);
                if (byPhone == null) {
                    // 如果该手机号未注册，自动注册
                    byPhone = new UserAccount();
                    byPhone.setPhoneAreaCode(phoneAreaCode);
                    byPhone.setPhone(phone);
                    byPhone = userAccountService.createUserAccount(byPhone);
                }
                // 生成令牌
                String token = userAccountTokenService.generateToken(byPhone.getId());
                return new LoginVO()
                        .setToken(token)
                        .setUserAccount(byPhone);
            }
        }

        // 验证码校验
        Boolean verify = verificationCodeService.verify(sendVerificationCodeDTO, verificationCode);
        if (!verify) {
            throw BaseException.of("verificationCodeOfSmsError", "短信验证码错误");
        }
        // 根据手机号查询用户
        UserAccount byPhone = repository.findByPhoneAreaCodeAndPhone(phoneAreaCode, phone);
        if (byPhone == null) {
            // 如果该手机号未注册，自动注册
            byPhone = new UserAccount();
            byPhone.setPhoneAreaCode(phoneAreaCode);
            byPhone.setPhone(phone);
            byPhone = userAccountService.createUserAccount(byPhone);
        }
        // 生成令牌
        String token = userAccountTokenService.generateToken(byPhone.getId());
        return new LoginVO()
                .setToken(token)
                .setUserAccount(byPhone);
    }

    @Override
    public LoginVO loginByEmailAndVerificationCode(String email, String verificationCode) {
        SendVerificationCodeDTO sendVerificationCodeDTO = new SendVerificationCodeDTO()
                .setTo(email)
                .setTypeCode(VerificationCodeTypeCodeEnum.EMAIL)
                .setSceneCode(UserAccountVerificationCodeSceneCodeEnums.LOGIN);
        // 验证码校验
        Boolean verify = verificationCodeService.verify(sendVerificationCodeDTO, verificationCode);
        if (!verify) {
            throw BaseException.of("verificationCodeOfEmailError", "邮箱验证码错误");
        }
        // 根据邮箱查询用户
        UserAccount byEmail = repository.findByEmail(email);
        if (byEmail == null) {
            // 如果该邮箱未注册，自动注册
            byEmail = new UserAccount();
            byEmail.setEmail(email);
            byEmail = userAccountService.createUserAccount(byEmail);
        }
        // 生成令牌
        String token = userAccountTokenService.generateToken(byEmail.getId());
        return new LoginVO()
                .setToken(token)
                .setUserAccount(byEmail);
    }

    @Override
    public LoginVO loginByPhoneAndPassword(String phoneAreaCode, String phone, String password) {
        // 根据手机号查询用户
        UserAccount byPhone = repository.findByPhoneAreaCodeAndPhone(phoneAreaCode, phone);
        if (byPhone == null) {
            // 该手机号未注册
            throw BaseException.of("phoneNotRegistered", "该手机号未注册");
        }
        // 如果密码为空
        if (byPhone.getPassword() == null) {
            // 该账号未设置密码
            throw BaseException.of("passwordNotSet", "该账号未设置密码");
        }
        if (!kantbootPassword.matches(password, byPhone.getPassword())) {
            // 手机号或密码错误
            throw BaseException.of("phoneOrPasswordError", "手机号或密码错误");
        }
        // 生成令牌
        String token = userAccountTokenService.generateToken(byPhone.getId());
        return new LoginVO()
                .setToken(token)
                .setUserAccount(byPhone);
    }

    @Override
    public LoginVO loginByEmailAndPassword(String email, String password) {
        // 根据邮箱查询用户
        UserAccount byEmail = repository.findByEmail(email);
        if (byEmail == null) {
            // 该邮箱未注册
            throw BaseException.of("emailNotRegistered", "该邮箱未注册");
        }
        // 如果密码为空
        if (byEmail.getPassword() == null) {
            // 该账号未设置密码
            throw BaseException.of("passwordNotSet", "该账号未设置密码");
        }
        if (!kantbootPassword.matches(password, byEmail.getPassword())) {
            // 邮箱或密码错误
            throw BaseException.of("emailOrPasswordError", "邮箱或密码错误");
        }
        // 生成令牌
        String token = userAccountTokenService.generateToken(byEmail.getId());
        return new LoginVO()
                .setToken(token)
                .setUserAccount(byEmail);
    }

    @Override
    public void logout() {
        // 退出登录
        userAccountTokenService.removeTokenBySelf();
    }
}
